package com.goldenSubmarine.ang.rotator 
{
	import com.greensock.easing.Quad;
	import com.greensock.TweenMax;
	import com.nuke.ui.LibBtn;
	import com.nuke.utils.Library;
	import com.nuke.utils.UserActivity;
	import flash.display.Hit;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.setTimeout;
	import flash.utils.Timer;
	import Singularity.demos.src.PSplineTest;
	import Singularity.Geom.BezierSpline;
	import Singularity.Geom.Knot;
	import Singularity.Geom.PSpline3;
	import flash.display.Sprite;
	import net.badimon.five3D.display.Scene3D;
	/**
	 * ...
	 * @author Bartłomiej JERZY
	 */
	public class Rotator extends Sprite
	{
		private var _scene						:Scene3D
		
			
		private var DIFF							:Number = 0.1
		private var NUM								:Number = 0
		private const UP_LIMIT						:Number = 0.8
		private const DN_LIMIT						:Number = 0.4
		private const AIM							:Number = 0.8
		private const ALPHA_SPEED					:Number = 20
		private const CENTER						:Number = (DN_LIMIT+UP_LIMIT)/2
		private const HIDE_ZONE						:Number = 1/ALPHA_SPEED
		
	
		private var _splineEdit						:Sprite = new Sprite()
		
		private var _splinePos						:Array = [
{x:657.8,y:-754.85},
{x:404.05,y:-501.85},
{x:97.05,y:-287.8},
{x:109.15,y:-222.5},
{x:-69.2,y:-199.55},
{x:-215.2,y:-162.55},
{x:-300.2,y:-84.55},
{x:-352.5,y:6.45}

																]
		private var _splinePosY						:Array = [
{x:541.95,y:-147.35},
{x:322.35,y:-40.65},
{x:265.7,y:-72.1},
{x:212.35,y:30.85},
{x:153.35,y:-141.3},
{x:42.7,y:3.85},
{x:-0.05,y:104.05}


																]
		private var _splinePosAng					:Array = [
																{x:565.15,y:104.45},
																{x:514.2,y:85},
																{x:458.95,y:48.4},
																{x:424.6,y:-9.2},
																{x:321,y:28.65},
																{x:236.15,y:7.35},
																{x:159.95,y:25.25},
																{x:103.7,y:39.5},
																{x:22.4,y:60.55},
															]
															
		private var _spline							:PSpline3
		private var _splineY						:PSpline3
		private var _splineAng						:PSpline3
		
		private var _edited							:PSpline3
		
		private var _timer							:Timer = new Timer(5000)
		
		
		private var _items							:Array = []
		private var _sort							:Array = []
		
		private var _nextArrow						:LibBtn
		private var _prevArrow						:LibBtn
		
		private var _knots							:Array = []
		
		private var _curr							:Item3D
		private var _currKnot						:Knot
		
		private var _currNum						:int = 0
		private var _sh								:Hit;
		private var _sh2							:Hit;
		private var _sh3							:Hit;
		
		private var _mid							:int
		private var _wheel							:Boolean = true
		private var _auto 							:Boolean = false
			
		private var _data							:XML
		private var _speed							:Number = 0;
		
		private var _userActivity					:UserActivity = new UserActivity(5000)
		
		public function Rotator($data:XML) 
		{
			_data = $data
			NUM = _data.item.length()
			addEventListener(Event.ADDED_TO_STAGE,addedToStage,false,0,true)
		}
		
		private function addedToStage(e:Event):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
			init()
			
		}
		
		private function init():void {
			_scene = new Scene3D()
			_spline = new PSpline3()
			_splineY = new PSpline3()
			_splineAng = new PSpline3()
			
			
			/*_sh= new Hit()
			_sh2= new Hit()
			_sh3= new Hit()
		
			_spline.container = _sh
			_splineY.container = _sh2
			_splineAng.container = _sh3
			var _knot:Knot*/
			
			
			for (var i:String in _splinePos) {
				/*_knot = new Knot(10,0xff0000)
				_knot.x = _splinePos[i].x
				_knot.y = _splinePos[i].y
				_knot.sp = _spline
				_knot.id = int(i)
				_knots.push(_knot)*/
				_spline.addControlPoint(_splinePos[i].x,_splinePos[i].y)
			}
			
			for (var j:String in _splinePosY) {
				/*_knot = new Knot(10,0x00ff00)
				_knot.x = _splinePosY[j].x
				_knot.y = _splinePosY[j].y
				_knot.sp = _splineY
				_knot.id = int(j)
				_knots.push(_knot)*/
				_splineY.addControlPoint(_splinePosY[j].x,_splinePosY[j].y)
			}
			
			for (var k:String in _splinePosAng) {
				/*_knot = new Knot(10,0x0000ff)
				_knot.x = _splinePosAng[k].x
				_knot.y = _splinePosAng[k].y
				_knot.sp = _splineAng
				_knot.id = int(k)
				_knots.push(_knot)*/
				_splineAng.addControlPoint(_splinePosAng[k].x,_splinePosAng[k].y)
			}
			
			/*_spline.color = 0x000000
			_spline.draw()
			_splineY.color = 0x000000
			_splineY.draw()
			_splineAng.color = 0x000000
			_splineAng.draw()
					
			_splineEdit.addChild(_sh)
			_splineEdit.addChild(_sh2)
			_splineEdit.addChild(_sh3)*/
		
			for (var l:String in _knots) {
				_knots[l].addEventListener(MouseEvent.MOUSE_DOWN, knotMouseDown, false, 0, true)
				
				_splineEdit.addChild(_knots[l])
			}
			
			/*_splineEdit.graphics.lineStyle(1, 0)
			_splineEdit.graphics.moveTo(0,-300)
			_splineEdit.graphics.lineTo(0, 300)
			_splineEdit.graphics.moveTo(-300,0)
			_splineEdit.graphics.lineTo(300, 0)
			_splineEdit.x = -400
			_splineEdit.y = 200*/
			
			
			
			initItems()
			
			_nextArrow = new LibBtn("arrow",{frame:50},{frame:1},0.3,0.5)		
			_prevArrow = new LibBtn("arrow",{frame:50},{frame:1},0.3,0.5)		
			_prevArrow.scaleX = -1
			_nextArrow.x  =   315
			_prevArrow.x = -315
			
			_nextArrow.addEventListener(Event.SELECT,prev,false,0,true)
			_prevArrow.addEventListener(Event.SELECT,next,false,0,true)
			
			stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler, false, 0, true)
			
			_timer.addEventListener(TimerEvent.TIMER,onTimer)
			_timer.start()
			
			_userActivity.addEventListener(UserActivity.USER_ACTIVITY,userActivityHandler)
			
			
			addChild(_scene)
			addChild(_nextArrow)
			addChild(_prevArrow)
			addChild(_splineEdit)
			addChild(_userActivity)
			
			//addEventListener(Event.ENTER_FRAME,update)	
		}
		
		private function userActivityHandler(e:Event):void 
		{
			if (_userActivity.active) {
				_timer.stop()
			}else {
				_timer.reset()
				_timer.start()
			}
		}
		
		private function onTimer(e:TimerEvent):void 
		{
			prev()
		}
		
		private function mouseWheelHandler(e:MouseEvent):void 
		{
			if (_wheel) {
				_wheel = false
				if (e.delta > 0) {
					next()
				}else {
					prev()
				}
				setTimeout(function():void{_wheel = true},50)
			}
		}
				
		private function next(e:Event = null):void {
			/*_timer.reset()
			_timer.start()*/
			_auto = false
			select(_curr.n)
		}
		
		private function prev(e:Event = null):void {
			/*_timer.reset()
			_timer.start()*/
			_auto = false
			select(_curr.p)
		}
				
		private function initItems():void {
			
			if(NUM){
				var num:int = Math.floor(1/DIFF);
				var n:int = NUM;
				while (n<num) {
					n += NUM;
				}
		
				
				for (var i:int = 0; i < n; i++) {
					//trace("###",i%NUM,_data.item[i%NUM])
					_items[i] = new Item3D(_data.item[(NUM-1)-i%NUM])
					_items[i].t = 0.5 + DIFF * i - (n - 1) * DIFF / 2
					_items[i].addEventListener(Event.SELECT,itemSelected)
					_items[i].id = (NUM-1)-i%NUM
					
					_scene.addChild(_items[i])
					
					if(i>0){
						_items[i - 1].n = _items[i]
						_items[i].p = _items[i - 1]
					}
				}
				
				
				
				_items[0].p = _items[_items.length-1]
				_items[_items.length - 1].n = _items[0]
				
				_curr = _items[NUM-1]
				_curr.t = AIM
				_curr.selected = true
				_speed = 1
				
				update()
				
				addChild(_scene)
				
			}else {
				trace("### OSŁOODPORNOŚĆ MODE: on")
			}
		}
		
		private function itemSelected(e:Event):void 
		{
			select(e.currentTarget as Item3D)
		}
		
		private function select($item:Item3D):void {
			
			TweenMax.killTweensOf(_curr)
			
			_curr.selected = false
			_curr = $item
			_curr.selected = true
			
			
			
			if (_curr.t < AIM) {
				_speed = 1
			}else {
				_speed = -1
			}

			TweenMax.to(_curr, 0.3 + Math.abs(_curr.t - AIM) * 3, { t:AIM, onUpdate:update, ease:Quad.easeOut } )
			
			dispatchEvent(new Event(Event.SELECT))
		}
		
		private function update(e:Event = null):void 
		{
			updatePosition()
			fix()
			render()
			
		}
		
		private function setAngle($item:Item3D):void {
			
			var _deltaX:Number  = _splineAng.getX($item.t-0.0001) - _splineAng.getX($item.t+0.0001)
			var _deltaZ:Number  = _splineAng.getY($item.t - 0.0001) - _splineAng.getY($item.t + 0.0001)
			var _angle:Number = 0
		
			if (_deltaX < 0 ){
				_angle = Math.atan2(_deltaZ, Math.abs(_deltaX))
			}else {
				_angle = Math.atan2(-_deltaZ, Math.abs(_deltaX))
			}
			
			$item.rotationY  = _angle * 180/Math.PI
			
		}
		
		private function setPosition($item:Item3D):void {
			$item.x = _spline.getX($item.t)
			$item.z = -_spline.getY($item.t)
			$item.y = _splineY.getY($item.t)
		}
				
		private function updatePosition():void {
			_currNum = _items.indexOf(_curr)
			
			for (var i:int = 0; i < _items.length; i++) {
				if (i < _currNum) {
					_items[i].t = _curr.t- (_currNum-i)*DIFF
				}else if (i>_currNum){
					_items[i].t = _curr.t+ (i-_currNum)*DIFF
				}
				
			}
		}
		
		private function fix():void
		{
			if (_speed>0) {
				
				_mid = Math.round(_items.length / 2);
				
				while (_items[_mid].t > CENTER) {
					_items[_items.length-1].t = _items[0].t-DIFF;
					_items.splice(0,0,_items[_items.length-1]);
					_items.pop();
	
				}
			} else {
				
				_mid = Math.round(_items.length/2);
				
				while (_items[_mid].t < CENTER) {
					
					_items[0].t = _items[_items.length-1].t+DIFF;
					_items.push(_items[0]);
					_items.splice(0, 1);
				}
			}
		}
		
		private function render():void {

			for (var i:int = 0; i < _items.length; i++) {
				if(_items[i].t >=DN_LIMIT-HIDE_ZONE && _items[i].t <= UP_LIMIT+HIDE_ZONE){
										
					if (!_scene.contains(_items[i])) {
						_scene.addChild(_items[i])
					}
					_items[i].mouseEnabled = true
					TweenMax.to(_items[i],0.3,{autoAlpha:1})
					_scene.setChildIndex(_items[i], _scene.numChildren-1)
					
				}else {
					_items[i].mouseEnabled = false
					TweenMax.to(_items[i], 0.1, { autoAlpha:0, onComplete:removeItem, onCompleteParams:[_items[i]] } )
				}
				
				setPosition(_items[i])
				setAngle(_items[i])
			}
			
		}
		
		private function removeItem(i:Item3D):void
		{
			if(_scene.contains(i)) _scene.removeChild(i)
		}
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		//////////////////////////////////////////////////////////////////////
		private function knotMouseDown(e:MouseEvent):void 
		{
			stage.addEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove,false,0,true)
			stage.addEventListener(MouseEvent.MOUSE_UP, knotMouseUp, false, 0, true)
			
			_currKnot = e.target as Knot
			_currKnot.startDrag()
		}
		private function knotMouseMove(e:MouseEvent):void 
		{
			_currKnot.sp.moveControlPoint(_currKnot.id,_currKnot.x,_currKnot.y)
			_currKnot.sp.draw()
		}
		private function knotMouseUp(e:MouseEvent):void 
		{
			stage.removeEventListener(MouseEvent.MOUSE_MOVE,knotMouseMove)
			stage.removeEventListener(MouseEvent.MOUSE_UP, knotMouseUp)
			_currKnot.stopDrag()
			
			trace("#### KNOTS COORDS ####")
			var _sp:PSpline3 = _knots[0].sp
			trace("#######  knoty z ",_sp)
			for (var i:String in _knots) {
				if (_sp != _knots[i].sp) {
					_sp = _knots[i].sp
					trace("#######  knoty z ",_sp)
				}
				trace("{x:"+_knots[i].x+",y:"+_knots[i].y+"}")
			}
		}
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////

	}

}